/*
* @Description:合约管理-结构体布局器
* @Author: lil
* @Date: 2021/11/30
**/
<template>
  <div class="structure-layout" v-loading="loading">
    <el-row type="flex" justify="space-around">
      <el-col :lg="5" :xl="5">
        <div class="structure-box" draggable="true" @dragstart="drag($event)">
          <el-button type="primary" class="structure-btn">结构体</el-button>
        </div>
      </el-col>
      <el-col :lg="11" :xl="12">
        <!-- V2.2版本暂时不需要 -->
        <div class="main-hd clearfix" v-if="!toUpgrade">
          <div class="save" @click="saveForm">暂存</div>
        </div>
        <div class="main-bd" :class="{isUpgrade:toUpgrade}">
          <div class="structure-content" @drop="drop($event)" @dragover="allowDrop($event)">
            <ul v-if="structureList">
              <li v-for="(item, idx) in structureList" :key="idx + 'jgt'" class="clearfix"
                :class="{ active: currentNode == idx }">
                <div class="structure" @click="editProperty(idx)">
                  {{ item.name }}
                </div>
                <div class="operate" v-if="currentNode == idx">
                  <div class="copy" @click="copyStructure(item, idx)">
                    <i class="el-icon-document-copy"></i>复制
                  </div>
                  <div class="delete" @click="deleteStructure(idx)">
                    <i class="el-icon-delete"></i>删除
                  </div>
                </div>
              </li>
            </ul>
          </div>
          <el-button type="primary" class="submit" v-html="operation" @click="operateStructure"></el-button>
        </div>
      </el-col>
      <el-col :lg="7" :xl="6">
        <p class="title">结构体属性</p>
        <el-form v-if="currentNode!=null" ref="form" :model="form" :rules="rules" label-width="97px">
          <div class="name">
            <el-form-item label="结构体名称:" prop="struName">
              <el-input v-model="form.struName"></el-input>
            </el-form-item>
            <el-form-item label="中文名称:" prop="chName">
              <el-input v-model="form.chName"></el-input>
              <span class="hint">仅用于页面展示及统计使用</span>
            </el-form-item>
          </div>
          <div style="padding: 10px">
            <el-form-item label="结构体主键:" class="is-required" prop="struMajorKey" :rules="{
                  validator: (rule, value, callback)=>{
                      checkStruMajorKey(rule, value, callback,form.struMajorKey[currentNode]);
                  }, trigger: 'change' 
                }">
              <el-select v-model="form.struMajorKey[currentNode]">
                <el-option v-for="(list, idx) in majorKeyList[currentNode]" :key="idx" :label="list" :value="list">
                </el-option>
              </el-select>
            </el-form-item>
          </div>
          <div class="data-box">
            <template v-if="form.dataList">
              <div class="data" v-for="(item, idx) in form.dataList[this.currentNode]" :key="idx + 'data'">
                <p class="subtitle">数据{{ idx + 1 }}</p>
                <el-form-item label="数据名称:" class="is-required" prop="dataName" :rules="{
                  validator: (rule, value, callback)=>{
                      checkDataName(rule, value, callback,item);
                  }, trigger: 'change' 
                }">
                  <el-input v-model="item.dataName" @focus="focusDataName($event,currentNode)"
                    @input="updateDataName(currentNode, idx)"></el-input>
                </el-form-item>
                <el-form-item label="数据类型:" class="is-required" prop="dataType" :rules="{
                  validator: (rule, value, callback)=>{
                      checkDataType(rule, value, callback,item);
                  }, trigger: 'change' 
                }">
                  <el-select v-model="item.dataType" @change="updateDataType">
                    <el-option v-for="(type, index) in dataType" :label="type" :value="type" :key="index + 'type'">
                    </el-option>
                  </el-select>
                  <i class="el-icon-circle-plus-outline" @click="addData"></i>
                  <i v-if="idx != 0" class="el-icon-delete" @click="deleteData(idx)"></i>
                </el-form-item>
              </div>
            </template>
          </div>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>
<script>
  import {
    getCCStructList,
    saveChainCode,
    submitUpdateInterface,
    submitUpgradeChaincode,
  } from "@/api/blockchain/blockchaindeploy";
  import {
    debounce
  } from "@/utils/debounce"
  export default {
    props: ["operation", "versionCode", "chainCodeName", "toUpgrade"],
    data() {

      let checkDataName = (rule, value, callback, item) => {
        let reg = /^\d/;
        if (!item || !item.dataName) {
          callback("数据名称不能为空！");
        } else if (reg.test(item.dataName)) {
          callback("首字符不能为数字！");
        }
        callback();
      }
      let checkDataType = (rule, value, callback, item) => {
        if (!item || !item.dataType) {
          callback("数据类型不能为空！");
        }
        callback();
      }
      let checkStruMajorKey = (rule, value, callback, item) => {
        if (!item) {
          callback("结构体主键不能为空！");
        }
        callback();
      }
      let checkCName = (rule, value, callback) => {
        var reg = /^[\u4E00-\u9FA5]+$/;
        if (value == '') {
          callback(new Error('中文名称不能为空!'));
        } else if (!reg.test(value)) {
          callback(new Error('请输入中文名称!'));
        } else {
          callback();
        }
      }
      let checkName = (rule, value, callback) => {
        let reg = /^\d/;
        if (value == '') {
          callback(new Error('结构体名称不能为空!'));
        } else if (reg.test(value)) {
          callback(new Error('首字符不能为数字!'));
        } else {
          callback();
        }
      }
      return {
        checkDataName,
        checkDataType,
        checkStruMajorKey,
        checkCName,
        checkName,
        form: {
          struName: "",
          chName: "",
          struMajorKey: [],
          dataList: [],
        },
        initVersionCode: "",
        initChainCodeName: "",
        structureList: [],
        currentNode: null,
        majorKeyList: [],
        saveData: [],
        tempList: [],
        flag: false,
        dataType: ["int", "string"],
        rules: {
          struName: [{
            required: true,
            validator: checkName,
            trigger: "change",
          }, ],
          chName: [{
            required: true,
            validator: checkCName,
            trigger: "change",
          }, ],
          struMajorKey: [{
            required: true,
            message: "请设置一个主键！",
            trigger: "change",
          }, ]
        },
        loading: false
      };
    },
    watch: {
      "form.struName": {
        deep: true,
        handler(newVal) {
          if (this.currentNode == null) return;
          this.structureList[this.currentNode].name = newVal;
        },
      },
      "form.chName": {
        deep: true,
        handler(newVal) {
          if (this.currentNode == null) return;
          this.structureList[this.currentNode].chName = newVal;
        },
      },
    },
    mounted() {
      this.getallCCStructList();
    },
    destroyed() {
      sessionStorage.setItem("contractName", "");
      sessionStorage.setItem("contractVersion", "");
    },
    methods: {
      getallCCStructList() {
        let _this = this;
        if (sessionStorage.getItem("contractName").length != 0) {
          _this.initChainCodeName = JSON.parse(
            JSON.stringify(sessionStorage.getItem("contractName"))
          );
          _this.initVersionCode = JSON.parse(
            JSON.stringify(sessionStorage.getItem("contractVersion"))
          );
        } else {
          _this.initChainCodeName = _this.chainCodeName;
          _this.initVersionCode = _this.versionCode;
        }
        getCCStructList(_this.initChainCodeName, _this.initVersionCode)
          .then(function (res) {
            _this.structureList = [];
            _this.majorKeyList = [];
            _this.form.dataList = [];
            for (let i = 0; i < res.data.length; i++) {
              var dataListTemp = [];
              var majorListTemp = [];
              _this.structureList.push({
                name: "",
                chName: "",
              });
              _this.structureList[i].name = res.data[i].struct_english_name;
              _this.structureList[i].chName = res.data[i].struct_chinese_name;
              for (
                let j = 0; j < res.data[i].struct_data.split(";").length; j++
              ) {
                if (res.data[i].struct_data.split(";")[j].length != 0) {
                  dataListTemp.push({
                    dataName: "",
                    dataType: "",
                  });
                  dataListTemp[j].dataName = res.data[i].struct_data
                    .split(";")[j].split(",")[0];
                  dataListTemp[j].dataType = res.data[i].struct_data
                    .split(";")[j].split(",")[1];
                  majorListTemp.push(dataListTemp[j].dataName);
                }
              }
              // majorListTemp.push(res.data[i].struct_key);
              _this.form.struMajorKey.push(res.data[i].struct_key);
              _this.majorKeyList.push(majorListTemp);
              _this.form.dataList.push(dataListTemp);
            }
          })
          .catch((err) => {
            console.log(err);
          });
      },
      /** 拖拽 */
      drag() {},
      /** 允许放下拖拽 */
      allowDrop(ev) {
        ev.preventDefault();
      },
      /** 放下 */
      drop() {
        let item = {
          name: "",
          chName: "",
        };
        this.structureList.push(item);
        this.majorKeyList.push([]);
        let obj = {
          dataName: "",
          dataType: "",
        };
        this.form.dataList[this.form.dataList.length] = [obj];
      },
      /** 修改属性 */
      editProperty(index) {
        this.currentNode = index;
        this.form.struName = this.structureList[index].name;
        this.form.chName = this.structureList[index].chName;
        this.$nextTick(() => {
          this.$refs.form.clearValidate();
        })
      },
      /** 删除结构体 */
      deleteStructure(index) {
        if (this.structureList.length == 1) {
          this.$message.warning('至少保留一个结构体！');
          return
        }
        this.structureList.splice(index, 1);
        this.form.dataList.splice(index, 1);
        this.majorKeyList.splice(index, 1);
        this.form.struMajorKey.splice(this.currentNode, 1);
        this.currentNode = null;
        this.form.struName = "";
        this.form.chName = "";
      },
      /** 复制结构体 */
      copyStructure(item, index) {
        this.$refs.form.validate((valid) => {
          if (valid) {
            let objItem = JSON.parse(JSON.stringify(item));
            this.structureList.push(objItem);
            let tempMajorKeyList = JSON.parse(
              JSON.stringify(this.majorKeyList[index])
            );
            this.majorKeyList.push(tempMajorKeyList);
            let tempStruMajorKey = JSON.parse(
              JSON.stringify(this.form.struMajorKey[index])
            );
            this.form.struMajorKey[this.structureList.length - 1] = tempStruMajorKey;
            let tempDataList = JSON.parse(JSON.stringify(this.form.dataList[index]));
            this.form.dataList.push(tempDataList);
          }
        })
      },
      /** 新增 */
      addData() {
        let item = {
          dataName: "",
          dataType: "",
        };
        this.form.dataList[this.currentNode].push(item);
        this.$forceUpdate();
      },
      /** 删除 */
      deleteData(index) {
        if (
          this.form.dataList[this.currentNode][index].dataName ==
          this.form.struMajorKey[this.currentNode]
        ) {
          this.form.struMajorKey[this.currentNode] = "";
        }
        this.form.dataList[this.currentNode].splice(index, 1);
        this.majorKeyList[this.currentNode].splice(index, 1);
        this.$nextTick(() => {
          this.$refs.form.clearValidate();
        })
      },
      /** 保存 */
      saveForm() {
        debounce(() => {
          if (this.structureList.length == 0) {
            this.$message.warning("请先创建结构体！");
            return;
          }
          if (this.$refs.form == undefined) {
            if (this.currentNode == null) {
              this.$message.warning("请编辑结构体信息！");
              return;
            }
          }
          let _this = this;
          let dataArr = [];
          if (sessionStorage.getItem("contractName").length != 0) {
            _this.initChainCodeName = JSON.parse(
              JSON.stringify(sessionStorage.getItem("contractName"))
            );
            _this.initVersionCode = JSON.parse(
              JSON.stringify(sessionStorage.getItem("contractVersion"))
            );
          } else {
            _this.initChainCodeName = _this.chainCodeName;
            _this.initVersionCode = _this.versionCode;
          }
          for (let i = 0; i < _this.form.struMajorKey.length; i++) {
            let tempArr = [];
            _this.form.dataList[i].forEach((item) => {
              tempArr.push(Object.values(item).join(","));
            });
            _this.tempList = tempArr;
            var obj = {
              struct_english_name: _this.structureList[i].name,
              struct_chinese_name: _this.structureList[i].chName,
              struct_data: _this.tempList.join(";"),
              struct_key: _this.form.struMajorKey[i],
            };
            dataArr.push(obj);
            // this.saveData.push(obj);
          }
          _this.saveData = dataArr;

          // 嵌套结构体
          // _this.structureList.forEach((item) => {
          //   if (_this.dataType.indexOf(item.name) == -1) {
          //     _this.dataType.push(item.name);
          //   }
          // });

          let structNameArr = [];
          _this.saveData.forEach((item) => {
            structNameArr.push(item.struct_english_name);
          })
          // 多个结构体同名校验
          if ((new Set(structNameArr)).size != structNameArr.length) {
            this.$message.warning('存在同名结构体！')
            return
          }
          // 多个结构体必填项校验
          if (this.saveData.length) {
            for (let i = 0; i < this.form.dataList.length; i++) {
              if (this.currentNode != i) {
                if (this.structureList[i].name == '' || this.structureList[i].chName == '' ||
                  this.form.struMajorKey[i] == undefined) {
                  this.$message.warning(`结构体${this.structureList[i].name}中有必填项未填写！`);
                  return
                };
                for (let j = 0; j < this.form.dataList[i].length; j++) {
                  if (this.form.dataList[i][j].dataName == '' || this.form.dataList[i][j].dataType == '') {
                    this.$message.warning(`结构体${this.structureList[i].name}中有数据未填写完整！`);
                    return
                  }
                }
              }
            }
          }
          this.$refs.form.validate((valid) => {
            if (valid) {
              var _this = this;
              saveChainCode(
                  _this.initChainCodeName,
                  _this.initVersionCode,
                  _this.saveData
                )
                .then(function (res) {
                  _this.$message({
                    type: "success",
                    message: "保存成功!",
                  });
                  _this.$emit("close-Setdialog");
                  sessionStorage.setItem("contractName", "");
                  sessionStorage.setItem("contractVersion", "");
                })
                .catch((err) => {
                  console.log(err);
                });
            }
          });
          _this.$forceUpdate();
        }, 500)
      },
      focusDataName(val, currentNode) {
        if (val.path[0].value == this.form.struMajorKey[currentNode] && this.form.struMajorKey[currentNode] != '') {
          this.flag = true;
        } else {
          this.flag = false;
        }
      },
      /** 更新数据名 */
      updateDataName(currentNode, idx) {
        let arr = this.form.dataList[this.currentNode];
        if (this.flag) {
          this.form.struMajorKey[currentNode] = arr[idx].dataName;
        }
        for (var i = 0; i < arr.length - 1; i++) {
          for (var j = i + 1; j < arr.length; j++) {
            if (arr[i].dataName === arr[j].dataName) {
              this.$message.error("数据名称不能相同");
              arr[j].dataName = "";
            }
          }
        }

        this.form.dataList[this.currentNode].forEach((item, idx) => {
          this.$set(this.majorKeyList[this.currentNode], idx, item.dataName);
        });
        this.$forceUpdate();
      },
      /** 更新数据类型 */
      updateDataType(val) {
        if (this.structureList[this.currentNode].name == val) {
          this.$message.warning("不能嵌套自身！");
          return;
        }
        this.$forceUpdate();
      },
      /** 提交/升级 */
      operateStructure() {
        debounce(() => {
          let _this = this;
          let dataArr = [];
          if (sessionStorage.getItem("contractName").length != 0) {
            _this.initChainCodeName = JSON.parse(
              JSON.stringify(sessionStorage.getItem("contractName"))
            );
            _this.initVersionCode = JSON.parse(
              JSON.stringify(sessionStorage.getItem("contractVersion"))
            );
          } else {
            _this.initChainCodeName = _this.chainCodeName;
            _this.initVersionCode = _this.versionCode;
          }
          for (let i = 0; i < _this.form.struMajorKey.length; i++) {
            let tempArr = [];
            if (_this.form.dataList.length > 0) {
              _this.form.dataList[i].forEach((item) => {
                tempArr.push(Object.values(item).join(","));
              });
            }
            _this.tempList = tempArr;
            var obj = {
              struct_english_name: _this.structureList[i].name,
              struct_chinese_name: _this.structureList[i].chName,
              struct_data: _this.tempList.join(";"),
              struct_key: _this.form.struMajorKey[i],
            };
            dataArr.push(obj);
          }
          _this.saveData = dataArr;

          // 嵌套结构体
          // _this.structureList.forEach((item) => {
          //   if (_this.dataType.indexOf(item.name) == -1) {
          //     _this.dataType.push(item.name);
          //   }
          // });

          if (this.structureList.length == 0) {
            this.$message.warning("请先创建结构体！");
            return;
          }
          if (this.$refs.form == undefined) {
            if (this.currentNode == null) {
              this.$message.warning("请编辑结构体信息！");
              return;
            }
          }
          let structNameArr = [];
          _this.saveData.forEach((item) => {
            structNameArr.push(item.struct_english_name);
          })
          // 多个结构体同名校验
          if ((new Set(structNameArr)).size != structNameArr.length) {
            this.$message.warning('存在同名结构体！')
            return
          }
          // 多个结构体必填项校验
          if (this.saveData.length) {
            for (let i = 0; i < this.form.dataList.length; i++) {
              if (this.currentNode != i) {
                if (this.structureList[i].name == '' || this.structureList[i].chName == '' ||
                  this.form.struMajorKey[i] == undefined) {
                  this.$message.warning(`结构体${this.structureList[i].name}中有必填项未填写！`);
                  return
                };
                for (let j = 0; j < this.form.dataList[i].length; j++) {
                  if (this.form.dataList[i][j].dataName == '' || this.form.dataList[i][j].dataType == '') {
                    this.$message.warning(`结构体${this.structureList[i].name}中有数据未填写完整！`);
                    return
                  }
                }
              }
            }
          }
          if (_this.toUpgrade) {
            this.$refs.form.validate((valid) => {
              if (valid) {
                var _this = this;
                submitUpgradeChaincode(
                    _this.initChainCodeName,
                    _this.initVersionCode,
                    _this.saveData
                  )
                  .then(function (res) {
                    _this.$message({
                      type: "success",
                      message: "合约修改成功!",
                    });
                    _this.$emit("close-dialog");
                  })
                  .catch(() => {});
              }
            });
          } else {
            this.$refs.form.validate((valid) => {
              if (valid) {
                var _this = this;
                submitUpdateInterface(
                    _this.initChainCodeName,
                    _this.initVersionCode,
                    _this.saveData
                  )
                  .then(function (res) {
                    _this.$message({
                      type: "success",
                      message: "提交完毕!",
                    });
                    _this.$emit("close-Setdialog");
                    sessionStorage.setItem("contractName", "");
                    sessionStorage.setItem("contractVersion", "");
                  })
                  .catch((err) => {
                    console.log(err);
                  });
              }
            });
          }
          _this.$forceUpdate();
        }, 500)
      },
    },
  };

</script>
<style lang="scss" scoped>
  .structure-layout {
    background-color: #f2f4fa;
    padding: 20px 10px;

    .el-row {
      .el-col {
        height: 600px;

        &:nth-child(1) {
          padding-top: 40px;
          background: url(~@/assets/image/blockchain-layout-bg.png) no-repeat;
          background-size: 100% 100%;

          .structure-box {
            width: 180px;
            height: 46px;
            margin: 0 auto;
          }

          .el-button {
            width: 180px;
            height: 46px;
            color: #2e7dff;
            font-size: 18px;
            box-shadow: none;
            border-color: #649dfe !important;
            background-color: #ecf0fb !important;
          }
        }

        &:nth-child(2) {
          .main-hd {
            background-color: #fff;
            margin-bottom: 10px;
            font-size: 12px;
            color: #5d7092;
            overflow: hidden;
            border-radius: 15px 15px 0 0;

            div {
              float: right;
              cursor: pointer;

              &::before {
                content: "";
                display: block;
                margin-bottom: 10px;
              }
            }

            .save {
              background-color: #f6fdf5;
              padding: 10px 30px;

              &::before {
                width: 22px;
                height: 22px;
                background: url(~@/assets/image/blockchain-layout-save.png) no-repeat;
                background-size: 100% 100%;
              }
            }
          }

          .main-bd {
            background-color: #fff;
            min-height: 525px;
            // min-height: 600px;
            position: relative;
            overflow: hidden;

            &.isUpgrade {
              min-height: 600px !important;

              .structure-content {
                height: 478px !important;
              }
            }

            .structure-content {
              height: 362px;
              // height: 478px;
              overflow-y: auto;

              &::-webkit-scrollbar {
                width: 6px;
                height: 1px;
                margin: 0 5px;
              }

              &::-webkit-scrollbar-thumb {
                border-radius: 6px;
                background: #d7d7d7;
              }

              &::-webkit-scrollbar-track {
                border-radius: 10px;
                background: #fff;
              }

              ul {
                padding: 0;

                li {
                  list-style: none;
                  margin: 10px auto;
                  padding: 15px 10px 15px 15px;
                  width: 304px;

                  .structure {
                    width: 206px;
                    height: 74px;
                    color: #fff;
                    font-size: 18px;
                    line-height: 74px;
                    border-radius: 6px;
                    text-align: center;
                    float: left;
                    cursor: pointer;
                    background-color: #a8c1ec;
                  }

                  &.active {
                    border: 1px dashed #358afc;

                    .structure {
                      background-color: #87aded;
                    }
                  }

                  .operate {
                    float: left;
                    font-size: 12px;
                    margin-left: 5px;

                    div {
                      width: 66px;
                      height: 29px;
                      line-height: 29px;
                      text-align: center;
                      border-radius: 5px;
                      cursor: pointer;

                      i {
                        margin-right: 5px;
                      }
                    }

                    .copy {
                      color: #2e7dff;
                      background-color: #ebf0f7;
                      margin-top: 4px;
                    }

                    .delete {
                      color: #f62b3e;
                      background-color: #f7ebeb;
                      margin-top: 8px;
                    }
                  }
                }
              }
            }

            .submit {
              position: absolute;
              bottom: 60px;
              left: 50%;
              margin-left: -56px;
            }
          }
        }

        &:nth-child(3) {
          background-color: #e7e9ef;
          border: 1px solid #d0d5e3;

          .title {
            font-size: 20px;
            color: #3c4551;
            margin: 0;
            height: 55px;
            line-height: 55px;
            padding-left: 10px;
            background-color: #cfd6e4;

            &::before {
              content: "";
              width: 5px;
              height: 16px;
              display: inline-block;
              border-radius: 10px;
              margin-right: 10px;
              background-color: #2e7dff;
            }
          }

          .el-form {
            background-color: transparent;
            padding: 0;

            &>>>.el-form-item__label {
              color: #505e83;
            }

            &>>>.el-input {
              width: 200px;

              .el-input__inner {
                border-color: #2e7dff;
              }
            }

            .name {
              border-bottom: 1px solid #d0d5e3;
              padding: 0 10px 10px;
              margin-top: 15px;
            }

            .hint {
              font-size: 12px;
              color: #9da2b3;
              display: inline-block;
            }

            .data-box {
              padding-top: 10px;
              height: 318px;
              overflow-y: auto;

              &::-webkit-scrollbar {
                width: 6px;
                height: 1px;
                margin: 0 5px;
              }

              &::-webkit-scrollbar-thumb {
                border-radius: 6px;
                background: #d7d7d7;
              }

              &::-webkit-scrollbar-track {
                border-radius: 10px;
                background: #fff;
              }

              .data {
                padding: 0 10px;
                margin-bottom: 25px;

                .subtitle {
                  color: #2e7dff;
                  margin: 0;

                  &::before {
                    content: "";
                    width: 3px;
                    height: 16px;
                    display: inline-block;
                    border-radius: 10px;
                    margin-right: 10px;
                    background-color: #2e7dff;
                    vertical-align: text-top;
                  }
                }

                .el-icon-circle-plus-outline {
                  color: #2e7dff;
                  font-size: 22px;
                  cursor: pointer;
                  vertical-align: middle;
                }

                .el-icon-delete {
                  padding: 2px;
                  font-size: 12px;
                  color: #f33d3d;
                  border-radius: 50%;
                  cursor: pointer;
                  border: 1px solid #f33d3d;
                }
              }
            }

            @media screen and (max-width: 1600px) {
              &>>>.el-input {
                width: 195px;
              }

              .data-box {
                height: 305px;
              }
            }

            @media screen and (max-width: 1440px) {
              &>>>.el-input {
                width: 158px;
              }
            }

            @media screen and (max-width: 1400px) {
              &>>>.el-input {
                width: 149px;
              }
            }

            @media screen and (max-width: 1366px) {
              &>>>.el-input {
                width: 141px;
              }
            }
          }
        }
      }
    }
  }

</style>
